#include "cfg.h"

int32_t do_load_cfg(struct ConnCtx* ctx, mxml_node_t* cfg, mxml_node_t* tree)
{
	/* lsi id */
	mxml_node_t* cfg_lsi_id = xml_find_child_element(cfg, tree, "lsi_id");
	if(!cfg_lsi_id)
	{
		fprintf(stderr, "config no lsi_id fail\n");
		return -1;
	}	
	ctx->cfg->lsi_id = atoi(xml_element_get_text(cfg_lsi_id));
	
	/* lsi ip */
	mxml_node_t* cfg_lsi_ip = xml_find_child_element(cfg, tree, "lsi_ip");
	if(!cfg_lsi_ip)
	{
		fprintf(stderr, "config no lsi_ip fail\n");
		return -1;
	}
	ctx->cfg->lsi_ip = lsi_addr_aton(xml_element_get_text(cfg_lsi_ip));

	/* lsi back-server ip */
	mxml_node_t* cfg_lsi_server_ip = xml_find_child_element(cfg, tree, "lsi_back_server_ip");
	if(!cfg_lsi_server_ip)
	{
		fprintf(stderr, "config no lsi_back_server_ip fail\n");
		return -1;
	}
	ctx->cfg->lsi_server_ip = lsi_addr_aton(xml_element_get_text(cfg_lsi_server_ip));

	/* lsi version */
	mxml_node_t* cfg_lsi_version = xml_find_child_element(cfg, tree, "lsi_version");
	if(!cfg_lsi_version)
	{
		fprintf(stderr, "config no lsi_version fail\n");
		return -1;
	}
	ctx->cfg->lsi_version = atoi(xml_element_get_text(cfg_lsi_version));

	/* pid file */
	snprintf(ctx->cfg->pid_file, 
		sizeof(ctx->cfg->pid_file),
		"/tmp/evconnsvrd_%d_%s.pid",
		ctx->cfg->lsi_id,
		lsi_addr_ntoa(ctx->cfg->lsi_ip));
	
	/* mm max size */
	mxml_node_t* cfg_mm_max_size = xml_find_child_element(cfg, tree, "mm_max_size");
	if(cfg_mm_max_size)
		ctx->cfg->mm_max_size = atoi(xml_element_get_text(cfg_mm_max_size));
	else
		ctx->cfg->mm_max_size = EVCONN_DEF_MM_MAX_SIZE;
	
	/* mm unit size */
	mxml_node_t* cfg_mm_unit_size = xml_find_child_element(cfg, tree, "mm_unit_size");
	if(cfg_mm_unit_size)
		ctx->cfg->mm_unit_size = atoi(xml_element_get_text(cfg_mm_unit_size));
	else
		ctx->cfg->mm_unit_size = EVCONN_DEF_MM_UNIT_SIZE;
	
	/* log type */
	mxml_node_t* cfg_log_type = xml_find_child_element(cfg, tree, "log_type");
	if(cfg_log_type)
		ctx->cfg->log_type = atoi(xml_element_get_text(cfg_log_type));
	else
		ctx->cfg->log_type = EVCONN_DEF_LOG_TYPE;

	/* log args */
	mxml_node_t* cfg_log_args = xml_find_child_element(cfg, tree, "log_args");
	if(cfg_log_args)
		ctx->cfg->log_args = atoi(xml_element_get_text(cfg_log_args));
	else
		ctx->cfg->log_args = EVCONN_DEF_LOG_ARGS;
	
	/* log name */
	mxml_node_t* cfg_log_name = xml_find_child_element(cfg, tree, "log_name");
	if(!cfg_log_name)
	{
		fprintf(stderr, "config no log_name fail\n");
		return -1;
	}
	snprintf(ctx->cfg->log_name, MAX_LOG_NAME_LEN, "%s", 
		xml_element_get_text(cfg_log_name));
	
	/* multi-thread */
	mxml_node_t* cfg_multi_thread = xml_find_child_element(cfg, tree, "multi_thread");
	if(cfg_multi_thread)
		ctx->cfg->multi_thread = atoi(xml_element_get_text(cfg_multi_thread));
	else
		ctx->cfg->multi_thread = EVCONN_DEF_MULTITHREAD;

	/* listen address */
	mxml_node_t* cfg_listen_addr = xml_find_child_element(cfg, tree, "listen_addr");
	if(!cfg_listen_addr)
	{
		fprintf(stderr, "config no listen address\n");
		return -1;
	}
	snprintf(ctx->cfg->listen_addr_str, 
			sizeof(ctx->cfg->listen_addr_str), 
			"%s",
			xml_element_get_text(cfg_listen_addr));
	ctx->cfg->sock_len = sizeof(struct sockaddr);
	if(evutil_parse_sockaddr_port(ctx->cfg->listen_addr_str,
		&ctx->cfg->listen_addr, &ctx->cfg->sock_len) < 0)
	{
		fprintf(stderr, "parse listen addr[%s] fail\n", ctx->cfg->listen_addr_str);
		return -1;
	}
	
	/* conn_buffer_size */
	mxml_node_t* cfg_conn_buffer_size = xml_find_child_element(cfg, tree, "conn_buffer_size");
	if(cfg_conn_buffer_size)
		ctx->cfg->conn_buffer_size = atoi(xml_element_get_text(cfg_conn_buffer_size));
	else
		ctx->cfg->conn_buffer_size = EVCONN_CONN_BUFFER_SIZE;

	/* conn_pool_threshold */
	mxml_node_t* cfg_conn_pool_threshold = xml_find_child_element(cfg, tree, "conn_pool_threshold");
	if(cfg_conn_pool_threshold)
		ctx->cfg->conn_pool_threshold = atoi(xml_element_get_text(cfg_conn_pool_threshold));
	else
		ctx->cfg->conn_pool_threshold = EVCONN_CONN_DEF_POOL_THRESHOLD;

	/* max connection in queue */
	mxml_node_t* cfg_max_queue_conn = xml_find_child_element(cfg, tree, "conn_max_in_queue");
	if(!cfg_max_queue_conn)
	{
		fprintf(stderr, "config no server_max_in_queue fail\n");
		return -1;
	}
	ctx->cfg->max_conn_in_queue = atoi(xml_element_get_text(cfg_max_queue_conn));
	
	return 0;
}

int32_t do_reload_cfg(struct ConnCtx* ctx, mxml_node_t* reload, mxml_node_t* tree)
{
	/* log level */
	mxml_node_t* cfg_log_level = xml_find_child_element(reload, tree, "log_level");
	if(cfg_log_level)
		ctx->cfg->log_level = atoi(xml_element_get_text(cfg_log_level));
	else
		ctx->cfg->log_level = EVCONN_DEF_LOG_LEVEL;

	/* tick interval */
	mxml_node_t* cfg_tick_interval = xml_find_child_element(reload, tree, "tick_interval");
	if(cfg_tick_interval)
		ctx->cfg->tick_interval = atoi(xml_element_get_text(cfg_tick_interval));
	else
		ctx->cfg->tick_interval = EVCONN_DEF_TICK_INTERVAL;

	/* timeout disconnect time, seconds */
	mxml_node_t* cfg_kick_timeout = xml_find_child_element(reload, tree, "kick_timeout");
	if(cfg_kick_timeout)
		ctx->cfg->kick_timeout = atoi(xml_element_get_text(cfg_kick_timeout));
	else
		ctx->cfg->kick_timeout = EVCONN_DEF_KICK_TIMEOUT;

	return 0;
}

int32_t load_cfg(struct ConnCtx* ctx, const char* cfg_file, int only_reload)
{
	assert(ctx && ctx->cfg);
	mxml_node_t* tree = xml_load_file(cfg_file);
	if(!tree) return -1;

	/* load config */
	mxml_node_t* cfg = xml_find_child_element(tree, tree, "config");
	if(!cfg)
	{
		fprintf(stderr, "config invalid fail\n");
		return -1;
	}
	if(!only_reload)
	{
		if(do_load_cfg(ctx, cfg, tree) < 0)
			return -1;
	}

	/* reload config */
	mxml_node_t* reload = xml_find_child_element(tree, tree, "reload");
	if(!reload)
	{
		fprintf(stderr, "reload config invalid fail\n");
		return -1;
	}
	if(do_reload_cfg(ctx, reload, tree) < 0)
		return -1;
	
	/* free xml node */
	xml_release(tree);
	
	return 0;
}

